using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using OpenComposite.Repository.Properties;
using System.Drawing.Printing;
using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using OpenComposite.Forms;

namespace OpenComposite.EII.RepositoryUIs
{
	public partial class UCDocumentation : RepositoryItemUI
	{
		#region Initialization
		public UCDocumentation(IServiceProvider serviceProvider)
			: base(serviceProvider)
		{
			_serviceProvider = serviceProvider;

			InitializeComponent();

			init();
		}
		private void init()
		{
			//lblLoading.Visible = false;
#if DEBUG
			btnLoad.Visible = true;
			rtfDoc.ReadOnly = false;
			txtName.ReadOnly = false;
#else
			btnLoad.Visible = false;
			rtfDoc.ReadOnly = true;
			rtfDoc.ShortcutsEnabled = false;
			rtfDoc.EnableAutoDragDrop = false;
			txtName.ReadOnly = true;
#endif
			rtfDoc.Visible = true;
			rtfDoc.Dock = DockStyle.Fill;
			pdfDoc.Visible = false;
			pdfDoc.Dock = DockStyle.Fill;
			pdfDoc.setShowToolbar(false);

			lblLoading.BringToFront();

			_tmpfile = Path.GetTempFileName();
		}
		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			try {
				Array.Clear(_documentBytes, 0, _documentBytes.Length);
				_documentBytes = null;
				GC.Collect();
			} catch { }
			// dispose acrobat reader
			try {
				if ( pdfDoc != null ) {
					this.pdfDoc.Dispose();
					this.pdfDoc = null;
				}
			} catch { }

			// delete temporary file
			try { if ( _tmpfile != null ) File.Delete(_tmpfile); } catch { }

			if ( disposing && ( components != null ) ) {
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#endregion

		#region Public Members

		#region Properties

		public override bool CanSave
		{
			get
			{
#if DEBUG
				return true;
#else
				return false;
#endif
			}
		}

		public override bool CanDelete
		{
			get
			{
#if DEBUG
				return true;
#else
				return false;
#endif
			}
		}

		public override IRepositoryItem RepositoryItem
		{
			get
			{
#if DEBUG
				save();
#endif
				return _doc;
			}
			set
			{
				if ( value is Documentation ) {
					_doc = (Documentation)value;
					load();
				}
			}
		}

		public override string TypeText
		{
			get { return "Documentation"; }
		}

		public override string TypeDescription
		{
			get { return ""; }
		}

		public void HideHeader()
		{
			label1.Visible = false;
			txtName.Visible = false;
			btnLoad.Visible = false;
			tableLayoutPanel1.Visible = false;
		}
		#endregion

		#endregion

		#region Private Members

		#region Constants
		private const string PDF = "PDF";
		private const string RTF = "RTF";
		#endregion

		#region Variables
		private Documentation _doc = null;
		private IServiceProvider _serviceProvider;
		private string _tmpfile = null;
		private int _zoom = 100;
		private bool _isvalidating = false;
		#endregion

		#region Methods
		private void load()
		{
			if ( _doc == null ) return;

			//_doc.Reload();

			txtName.Text = _doc.Name;

			showDocument();
		}
		private void save()
		{
			if ( _doc == null ) return;

			//_doc.Reload();

			_doc.Name = txtName.Text;

		}

		private byte[] _documentBytes;

		private void setDocument(string filename)
		{
			if ( Path.GetExtension(filename).ToLower() == ".pdf" ) {
				_doc.BinaryDocument = File.ReadAllBytes(filename);
				_doc.Description = PDF;
			} else {
				rtfDoc.LoadFile(filename);
				_doc.Document = rtfDoc.Rtf;
				_doc.Description = RTF;
			}
			_doc.Save();
		}
		private void showDocument()
		{
			if ( pdfDoc == null || pdfDoc.IsDisposed ) return;
			lblLoading.Visible = true;
			lblLoading.BringToFront();
			this.Refresh();
			object obj = pdfDoc.GetVersions();
			string[] versions = obj.ToString().Split(',');
			foreach ( string version in versions ) {
				try {
					string s = version.Substring(version.IndexOf('=') + 1);
					if ( string.IsNullOrEmpty(s) ) continue;
					Version v = new Version(s);
					if ( v.Major < 8 ) {
						InfoBox.Show("Adobe Reader or one of its components is older than version 8!" + Environment.NewLine +
							"You need Adobe Reader 8 or higher to view the documentation.",
							"Cannot load documentation", "Download latest Adobe Reader", "http://www.adobe.com/products/acrobat/readstep2.html");
						return;
					}
				} catch ( Exception ex ) {
					ErrorBox.Show(ex, "An error occured while initializing Adobe Reader!" + Environment.NewLine +
						"Please make sure Adobe Reader 8 or higher is installed correctly", false);
					return;
				}
			}
			this.SuspendLayout();
			bool isPDF = false;
			bool isRTF = false;
			try {
				if ( _doc.Description == PDF ) {
					if ( _documentBytes == null || _documentBytes != _doc.BinaryDocument ) {
						List<byte> bytes = new List<byte>();
						bytes.AddRange(_doc.BinaryDocument);
						bytes.InsertRange(0, new byte[] { 1, 9, 1, 4 });
						_documentBytes = bytes.ToArray();
					}
					File.WriteAllBytes(_tmpfile, _documentBytes);
					GC.Collect();
					pdfDoc.SuspendLayout();
					pdfDoc.LoadFile(_tmpfile);
					pdfDoc.setShowToolbar(false);
					pdfDoc.setPageMode("none");
					pdfDoc.ResumeLayout(true);
					isPDF = true;
				} else {
					rtfDoc.Rtf = _doc.Document;
					isRTF = true;
				}
				pdfDoc.Visible = isPDF;
				tsPDF.Visible = isPDF;
				rtfDoc.Visible = isRTF;
			} catch {
			} finally {
				this.ResumeLayout(true);
				lblLoading.Visible = false;
			}
		}
		private void setZoom()
		{
			tscmbZoom.Text = string.Format("{0} %", _zoom);
			pdfDoc.setZoom((float)_zoom);
		}
		private void validateZoom()
		{
			if ( _isvalidating || tscmbZoom.Text.StartsWith("Fit") ) return;
			_isvalidating = true;
			Regex regex = new Regex(@"\d+");
			Match match = regex.Match(tscmbZoom.Text);
			if ( match.Success ) {
				int z;
				if ( int.TryParse(match.Value, out z) ) {
					_zoom = z;
				}
			}
			setZoom();
			_isvalidating = false;
		}

		#endregion

		#region Event Handlers

		private void btnLoad_Click(object sender, EventArgs e)
		{
			if ( openRtfDlg.ShowDialog() == DialogResult.OK ) {
				setDocument(openRtfDlg.FileName);
				showDocument();
			}
		}

		private void rtfDoc_SelectionChanged(object sender, EventArgs e)
		{
#if !DEBUG
			rtfDoc.Select(0, 0);
#endif
		}

		private void tsbtnPrint_Click(object sender, EventArgs e)
		{
			pdfDoc.printWithDialog();
		}
		private void tsbtnPreviousPage_Click(object sender, EventArgs e)
		{
			pdfDoc.gotoPreviousPage();
		}
		private void tsbtnNextPage_Click(object sender, EventArgs e)
		{
			pdfDoc.gotoNextPage();
		}
		private void tsbtnFitWidth_Click(object sender, EventArgs e)
		{
			pdfDoc.setView("FitH");
			tscmbZoom.Text = "Fit Width";
		}
		private void tsbtnFitPage_Click(object sender, EventArgs e)
		{
			pdfDoc.setView("Fit");
			tscmbZoom.Text = "Fit";
		}
		private void tsbtnZoomIn_Click(object sender, EventArgs e)
		{
			if ( _zoom < 10000 ) {
				_zoom += 10;
				setZoom();
			}
		}
		private void tsbtnZoomOut_Click(object sender, EventArgs e)
		{
			if ( _zoom > 10 ) {
				_zoom -= 10;
				setZoom();
			}
		}
		private void tscmbZoom_Leave(object sender, EventArgs e)
		{
			validateZoom();
		}
		private void tscmbZoom_KeyUp(object sender, KeyEventArgs e)
		{
			if ( e.KeyCode == Keys.Enter ) {
				validateZoom();
			}
		}
		private void tscmbZoom_SelectedIndexChanged(object sender, EventArgs e)
		{
			validateZoom();
		}

		#endregion

		private void UCDocumentation_ControlAdded(object sender, ControlEventArgs e)
		{

		}

		#endregion

		private void UCDocumentation_ParentChanged(object sender, EventArgs e)
		{
			//if ( this.Visible )
			//    showDocument();
		}
	}

	public class AxAcroPDFEx : AxAcroPDFLib.AxAcroPDF
	{

		public AxAcroPDFEx()
			: base()
		{
		}

		protected override void CreateSink()
		{
			base.CreateSink();
		}

		public override bool LoadFile(string fileName)
		{
			bool ok = base.LoadFile(string.Format("{0}", fileName));
			File.Delete(fileName);
			return ok;
		}

		protected override void WndProc(ref Message m)
		{
			// try to catch the click on the save button!
			long lparam = m.LParam.ToInt64();
			if ( lparam == 26476561 ) {
			} else {
			}
			base.WndProc(ref m);
		}

		protected override void AttachInterfaces()
		{
			base.AttachInterfaces();
		}

		protected override void OnClick(EventArgs e)
		{
			base.OnClick(e);
		}

		protected override void OnMouseClick(MouseEventArgs e)
		{
			base.OnMouseClick(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			base.OnMouseUp(e);
		}

		public override void postMessage(object strArray)
		{
			base.postMessage(strArray);
		}

		protected override void OnNotifyMessage(Message m)
		{
			base.OnNotifyMessage(m);
		}

		public override void setShowToolbar(bool on)
		{
			base.setShowToolbar(on);
		}

		public override void setPageMode(string pageMode)
		{
			base.setPageMode(pageMode);
		}

		public override bool PreProcessMessage(ref Message msg)
		{
			return base.PreProcessMessage(ref msg);
		}
	}
}
